]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOS9/Mac OS Test Responder.c
mDNSResponder-107.tar.gz
[apple/mdnsresponder.git] / mDNSMacOS9 / Mac OS Test Responder.c
1 /*
2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22
23 Change History (most recent first):
24
25 $Log: Mac\040OS\040Test\040Responder.c,v $
26 Revision 1.24 2004/12/16 20:49:34 cheshire
27 <rdar://problem/3324626> Cache memory management improvements
28
29 Revision 1.23 2004/09/17 01:08:50 cheshire
30 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
31 The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
32 declared in that file are ONLY appropriate to single-address-space embedded applications.
33 For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
34
35 Revision 1.22 2004/08/13 23:25:01 cheshire
36 Now that we do both uDNS and mDNS, global replace "m->hostname" with
37 "m->MulticastHostname" for clarity
38
39 Revision 1.21 2004/03/12 21:30:25 cheshire
40 Build a System-Context Shared Library from mDNSCore, for the benefit of developers
41 like Muse Research who want to be able to use mDNS/DNS-SD from GPL-licensed code.
42
43 Revision 1.20 2004/02/09 23:23:32 cheshire
44 Advertise "IL 2\4th Floor.apple.com." as another test "browse domain"
45
46 Revision 1.19 2004/01/24 23:55:15 cheshire
47 Change to use mDNSOpaque16fromIntVal/mDNSVal16 instead of shifting and masking
48
49 Revision 1.18 2003/11/14 21:27:08 cheshire
50 <rdar://problem/3484766>: Security: Crashing bug in mDNSResponder
51 Fix code that should use buffer size MAX_ESCAPED_DOMAIN_NAME (1005) instead of 256-byte buffers.
52
53 Revision 1.17 2003/08/14 02:19:54 cheshire
54 <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
55
56 Revision 1.16 2003/08/12 19:56:24 cheshire
57 Update to APSL 2.0
58
59 */
60
61 #include <stdio.h> // For printf()
62 #include <string.h> // For strlen() etc.
63
64 #include <Events.h> // For WaitNextEvent()
65 #include <SIOUX.h> // For SIOUXHandleOneEvent()
66
67 #include "mDNSEmbeddedAPI.h" // Defines the interface to the client layer above
68
69 #include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
70
71 // These don't have to be globals, but their memory does need to remain valid for as
72 // long as the search is going on. They are declared as globals here for simplicity.
73 static mDNS m;
74 static mDNS_PlatformSupport p;
75 static ServiceRecordSet p1, p2, afp, http, njp;
76 static AuthRecord browsedomain1, browsedomain2;
77
78 // This sample code just calls mDNS_RenameAndReregisterService to automatically pick a new
79 // unique name for the service. For a device such as a printer, this may be appropriate.
80 // For a device with a user interface, and a screen, and a keyboard, the appropriate
81 // response may be to prompt the user and ask them to choose a new name for the service.
82 mDNSlocal void Callback(mDNS *const m, ServiceRecordSet *const sr, mStatus result)
83 {
84 switch (result)
85 {
86 case mStatus_NoError: debugf("Callback: %##s Name Registered", sr->RR_SRV.resrec.name->c); break;
87 case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", sr->RR_SRV.resrec.name->c); break;
88 case mStatus_MemFree: debugf("Callback: %##s Memory Free", sr->RR_SRV.resrec.name->c); break;
89 default: debugf("Callback: %##s Unknown Result %d", sr->RR_SRV.resrec.name->c, result); break;
90 }
91
92 if (result == mStatus_NameConflict) mDNS_RenameAndReregisterService(m, sr, mDNSNULL);
93 }
94
95 // RegisterService() is a simple wrapper function which takes C string
96 // parameters, converts them to domainname parameters, and calls mDNS_RegisterService()
97 mDNSlocal void RegisterService(mDNS *m, ServiceRecordSet *recordset,
98 UInt16 PortAsNumber, const char txtinfo[],
99 const domainlabel *const n, const char type[], const char domain[])
100 {
101 domainname t;
102 domainname d;
103 char buffer[MAX_ESCAPED_DOMAIN_NAME];
104 UInt8 txtbuffer[512];
105
106 MakeDomainNameFromDNSNameString(&t, type);
107 MakeDomainNameFromDNSNameString(&d, domain);
108
109 if (txtinfo)
110 {
111 strncpy((char*)txtbuffer+1, txtinfo, sizeof(txtbuffer)-1);
112 txtbuffer[0] = (UInt8)strlen(txtinfo);
113 }
114 else
115 txtbuffer[0] = 0;
116
117 mDNS_RegisterService(m, recordset,
118 n, &t, &d, // Name, type, domain
119 mDNSNULL, mDNSOpaque16fromIntVal(PortAsNumber),
120 txtbuffer, (mDNSu16)(1+txtbuffer[0]), // TXT data, length
121 mDNSNULL, 0, // Subtypes (none)
122 mDNSInterface_Any, // Interface ID
123 Callback, mDNSNULL); // Callback and context
124
125 ConvertDomainNameToCString(recordset->RR_SRV.resrec.name, buffer);
126 printf("Made Service Records for %s\n", buffer);
127 }
128
129 // RegisterFakeServiceForTesting() simulates the effect of services being registered on
130 // dynamically-allocated port numbers. No real service exists on that port -- this is just for testing.
131 mDNSlocal void RegisterFakeServiceForTesting(mDNS *m, ServiceRecordSet *recordset, const char txtinfo[],
132 const char name[], const char type[], const char domain[])
133 {
134 static UInt16 NextPort = 0xF000;
135 domainlabel n;
136 MakeDomainLabelFromLiteralString(&n, name);
137 RegisterService(m, recordset, NextPort++, txtinfo, &n, type, domain);
138 }
139
140 // CreateProxyRegistrationForRealService() checks to see if the given port is currently
141 // in use, and if so, advertises the specified service as present on that port.
142 // This is useful for advertising existing real services (Personal Web Sharing, Personal
143 // File Sharing, etc.) that currently don't register with mDNS Service Discovery themselves.
144 mDNSlocal OSStatus CreateProxyRegistrationForRealService(mDNS *m, UInt16 PortAsNumber, const char txtinfo[],
145 const char *servicetype, ServiceRecordSet *recordset)
146 {
147 InetAddress ia;
148 TBind bindReq;
149 OSStatus err;
150 TEndpointInfo endpointinfo;
151 EndpointRef ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, &endpointinfo, &err);
152 if (!ep || err) { printf("OTOpenEndpoint (CreateProxyRegistrationForRealService) failed %d", err); return(err); }
153
154 ia.fAddressType = AF_INET;
155 ia.fPort = mDNSOpaque16fromIntVal(PortAsNumber).NotAnInteger;
156 ia.fHost = 0;
157 bindReq.addr.maxlen = sizeof(ia);
158 bindReq.addr.len = sizeof(ia);
159 bindReq.addr.buf = (UInt8*)&ia;
160 bindReq.qlen = 0;
161 err = OTBind(ep, &bindReq, NULL);
162
163 if (err == kOTBadAddressErr)
164 RegisterService(m, recordset, PortAsNumber, txtinfo, &m->nicelabel, servicetype, "local.");
165 else if (err)
166 debugf("OTBind failed %d", err);
167
168 OTCloseProvider(ep);
169 return(noErr);
170 }
171
172 // Done once on startup, and then again every time our address changes
173 mDNSlocal OSStatus mDNSResponderTestSetup(mDNS *m)
174 {
175 char buffer[MAX_ESCAPED_DOMAIN_NAME];
176 mDNSv4Addr ip = m->HostInterfaces->ip.ip.v4;
177
178 ConvertDomainNameToCString(&m->MulticastHostname, buffer);
179 printf("Name %s\n", buffer);
180 printf("IP %d.%d.%d.%d\n", ip.b[0], ip.b[1], ip.b[2], ip.b[3]);
181
182 printf("\n");
183 printf("Registering Service Records\n");
184 // Create example printer discovery records
185 //static ServiceRecordSet p1, p2;
186
187 #define SRSET 0
188 #if SRSET==0
189 RegisterFakeServiceForTesting(m, &p1, "path=/index.html", "Web Server One", "_http._tcp.", "local.");
190 RegisterFakeServiceForTesting(m, &p2, "path=/path.html", "Web Server Two", "_http._tcp.", "local.");
191 #elif SRSET==1
192 RegisterFakeServiceForTesting(m, &p1, "rn=lpq1", "Epson Stylus 900N", "_printer._tcp.", "local.");
193 RegisterFakeServiceForTesting(m, &p2, "rn=lpq2", "HP LaserJet", "_printer._tcp.", "local.");
194 #else
195 RegisterFakeServiceForTesting(m, &p1, "rn=lpq3", "My Printer", "_printer._tcp.", "local.");
196 RegisterFakeServiceForTesting(m, &p2, "lrn=pq4", "My Other Printer", "_printer._tcp.", "local.");
197 #endif
198
199 // If AFP Server is running, register a record for it
200 CreateProxyRegistrationForRealService(m, 548, "", "_afpovertcp._tcp.", &afp);
201
202 // If Web Server is running, register a record for it
203 CreateProxyRegistrationForRealService(m, 80, "", "_http._tcp.", &http);
204
205 // And pretend we always have an NJP server running on port 80 too
206 //RegisterService(m, &njp, 80, "NJP/", &m->nicelabel, "_njp._tcp.", "local.");
207
208 // Advertise that apple.com. is available for browsing
209 mDNS_AdvertiseDomains(m, &browsedomain1, mDNS_DomainTypeBrowse, mDNSInterface_Any, "apple.com.");
210 mDNS_AdvertiseDomains(m, &browsedomain2, mDNS_DomainTypeBrowse, mDNSInterface_Any, "IL 2\\4th Floor.apple.com.");
211
212 return(kOTNoError);
213 }
214
215 // YieldSomeTime() just cooperatively yields some time to other processes running on classic Mac OS
216 mDNSlocal Boolean YieldSomeTime(UInt32 milliseconds)
217 {
218 extern Boolean SIOUXQuitting;
219 EventRecord e;
220 WaitNextEvent(everyEvent, &e, milliseconds / 17, NULL);
221 SIOUXHandleOneEvent(&e);
222 return(SIOUXQuitting);
223 }
224
225 int main()
226 {
227 mStatus err;
228 Boolean DoneSetup = false;
229
230 SIOUXSettings.asktosaveonclose = false;
231 SIOUXSettings.userwindowtitle = "\pMulticast DNS Responder";
232
233 printf("Multicast DNS Responder\n\n");
234 printf("This software reports errors using MacsBug breaks,\n");
235 printf("so if you don't have MacsBug installed your Mac may crash.\n\n");
236 printf("******************************************************************************\n");
237
238 err = InitOpenTransport();
239 if (err) { debugf("InitOpenTransport failed %d", err); return(err); }
240
241 err = mDNS_Init(&m, &p, mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
242 mDNS_Init_AdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
243 if (err) return(err);
244
245 while (!YieldSomeTime(35))
246 {
247 #if MDNS_ONLYSYSTEMTASK
248 // For debugging, use "#define MDNS_ONLYSYSTEMTASK 1" and call mDNSPlatformIdle() periodically.
249 // For shipping code, don't define MDNS_ONLYSYSTEMTASK, and you don't need to call mDNSPlatformIdle()
250 extern void mDNSPlatformIdle(mDNS *const m);
251 mDNSPlatformIdle(&m); // Only needed for debugging version
252 #endif
253 if (m.mDNSPlatformStatus == mStatus_NoError && !DoneSetup)
254 {
255 DoneSetup = true;
256 printf("\nListening for mDNS queries...\n");
257 mDNSResponderTestSetup(&m);
258 }
259 }
260
261 if (p1.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &p1);
262 if (p2.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &p2);
263 if (afp.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &afp);
264 if (http.RR_SRV.resrec.RecordType) mDNS_DeregisterService(&m, &http);
265 if (njp.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &njp);
266
267 mDNS_Close(&m);
268
269 return(0);
270 }